/**
 * @file Picture.hpp
 *
 * @date 20/12/2011
 * @author Tales 
 *
 */

#ifndef _MODEL_PICTURE_HPP_
#define _MODEL_PICTURE_HPP_

#include <deque>
#include "PictureState.hpp"

namespace yep
{
using namespace std;
class Command;

/**
 * @brief Uma imagem editável
 *
 * Esta classe é bem completa, permitindo refazer/desfazer alterações e salvar/carregar
 * imagens.
 *
 * Os formatos suportado são bmp e lbmp, um formato próprio bem simples (e provisório, deve
 * ser descontinuado em futuras releases) que consiste em um arquivo binário, com uma word (Uint16)
 * identificando a quantidade de camadas e sucessivos bmps representando cada camada.
 *
 */
class Picture
{
public:
	/**
	 * @brief Cria uma nova Picture
	 * @param w largura
	 * @param h altura
	 * @param bpp bits por pixel
	 */
	Picture(int w, int h, int bpp);

	/**
	 * @brief Carrega uma imagem de um arquivo
	 * @param file um SDL_RWops para o arquivo
	 * @param exportToBmp se true exporta a partir de um bmp (senão usa lbmp);
	 */
	Picture(SDL_RWops *file, bool importFromBmp);

	/**
	 * @brief Destrutor.
	 */
	~Picture();

	/**
	 * @brief Salva ou exporta a imagem
	 * @param file um SDL_RWops para o arquivo
	 * @param exportToBmp se true exporta pra bmp (senão usa lbmp)
	 */
	void save(SDL_RWops *file, bool exportToBmp);

	/**
	 * @brief Adiciona (e executa) um comando
	 * @param command o comando a ser executado
	 */
	void addCommand(Command *command);

	/**
	 * @brief Renderiza todas as camadas no destino
	 * @param dst destino
	 */
	void render(SDL_Surface *dst);

	/**
	 * @brief Checa se a ação atua pode ser desfeita
	 * @return true se pode desfazer
	 */
	bool canUndo();

	/**
	 * @brief Desfaz a ação atual
	 */
	void undo();

	/**
	 * @brief Desfaz todas as ações
	 */
	void revertAll();

	/**
	 * @brief Checa se é possível refazer uma ação
	 * @return true se pode resfazer
	 */
	bool canRedo();

	/**
	 * @brief Refaz uma ação
	 */
	void redo();

	/**
	 * @brief Apaga comandos anteriores e faz do estado atual o estado inicial.
	 */
	void doPermanently();

	/**
	 * @brief Copia um layer
	 * @param layer o número layer
	 * @return a cópia do layer. A posse desse ponteior é do receptor, ou seja, este deve
	 * 		se encarregar de liberar a memória da Surface.
	 */
	SDL_Surface *getCopy(size_t layer);

	/**
	 * @brief Copia uma porção de um layer
	 * @param layer o número layer
	 * @param slice a area a ser copiada
	 * @return a cópia. A posse desse ponteior é do receptor, ou seja, este deve
	 * 		se encarregar de liberar a memória da Surface.
	 */
	SDL_Surface *getCopy(size_t layer, const SDL_Rect &slice);

	/**
	 * @brief Conta os layers.
	 * @return a quantidade de layers.
	 */
	size_t getLayerCount();


	int getW() const;

	int getH() const;

private:
	PictureState first;
	PictureState *current;
	deque<Command*> commands;
	deque<Command*>::iterator currentCommand;
};

} /* namespace yep */
#endif /* _MODEL_PICTURE_HPP_ */
